// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using PfRep.Library;

using Data = PfRep.DataEntities;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;

namespace PfRep.Console
{
    public partial class IndexContentStatistics : Form
    {
        /// <summary>
        /// This is the worker thread does the indexing job. We have to
        /// keep a reference in case if we want to shut it down.
        /// </summary>
        private Thread backgroundIndexingThread = null;
        
        private Data.FolderTree _publicFolderTree;
        
        /// <summary>
        /// The public folder tree used as a parent of the
        /// content statistics
        /// </summary>
        public Data.FolderTree PublicFolderTree
        {
            get { return _publicFolderTree; }
            
            set 
            { 
                _publicFolderTree = value;
                txtPublicFolderTree.Text = PublicFolderTree.Name;
            }
        }

        /// <summary>
        /// The newly created content statistic's name
        /// </summary>
        public string NewlyCreatedContentStatisticsName = "";

        /// <summary>
        /// Indicates whether the user has cancelled the process or a new
        /// tree was succesfully created
        /// </summary>
        public bool UserCancelled = false;

        /// <summary>
        /// Sets the username on the UI. Used for unattended execution
        /// </summary>
        public string Username = "";
        
        /// <summary>
        /// Sets the password on the UI. Used for unattended execution
        /// </summary>
        public string Password = "";
        
        /// <summary>
        /// Commands to start indexing automatically. 
        /// If every information (PublicFolderTree, Username, Password) is specified,
        /// it will start automatically.
        /// </summary>
        public bool StartAutomatically = false;

        /// <summary>
        /// Initializes the form controls
        /// </summary>
        public IndexContentStatistics()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Enables/disables the OK button, based whether there are selected values in
        /// both comboboxes
        /// </summary>
        private void SetOkButton()
        {
            // If both options are selected, the OK button gets enabled, otherwise, disabled
            if (PublicFolderTree != null && PublicFolderTree.Name != null && PublicFolderTree.Name.Length > 0 &&
                txtContentStatisticsName.Text.Length > 0)
                cmdOK.Enabled = true;
            else
                cmdOK.Enabled = false;
        }

        /// <summary>
        /// Starts indexing based on the control values
        /// </summary>
        private void StartIndexing()
        {
            // Saves the username textbox's value to history
            SaveInputControlValues();

            // Save the statistic's name
            NewlyCreatedContentStatisticsName = txtContentStatisticsName.Text;

            lblCurrentOperation.Text = "Indexing contents";

            IndexManager indexManager = new IndexManager();

            // Subscribing to the progress update event
            indexManager.ProgressChanges += new IndexingProgress(IndexManager_ProgressChanges);
            indexManager.IndexingCompleted += new IndexingCompleted(indexManager_IndexingCompleted);
            indexManager.IndexingError += new IndexingError(indexManager_IndexingError);

            // Disable thread-safety test on controls. We know what we do ... :)
            Control.CheckForIllegalCrossThreadCalls = false;
            
            // Start indexing
            backgroundIndexingThread = new Thread(new ParameterizedThreadStart(ThreadProc));
            backgroundIndexingThread.Start(new ContentStatInputParams(indexManager, 
                txtContentStatisticsName.Text, PublicFolderTree.ID, PublicFolderTree.Url,
                txtUsername.Text, txtPassword.Text, Statistics.GetAllFolders(PublicFolderTree.ID)));

            UserCancelled = false;
        }

        #region Asynchronous processing functions - UI handlers, etc
        /// <summary>
        /// This is a function that starts the asynchronous processing
        /// </summary>
        /// <param name="stateInfo"></param>
        private void ThreadProc(object stateInfo)
        {
            // Convert the input params to the correct format
            ContentStatInputParams inputParams = stateInfo as ContentStatInputParams;

            // Extract the parameters and convert them to parameters on a function call
            if (inputParams != null)
                inputParams.IndexManager.CreateContentStatistics(inputParams.ContentStatisticsName,
                    inputParams.PublicFolderTreeID, inputParams.PublicFolderTreeUrl,
                    inputParams.Username, inputParams.Password, inputParams.FoldersToIndex);
            else
                PfRep.Common.Diagnostics.Trace("IndexContentStatistics.ThreadProc",
                    "ERROR: stateInfo is not ContentStatInputParams format");
        }

        /// <summary>
        /// Called when an error occurred while indexing on the 2nd thread
        /// </summary>
        /// <param name="e"></param>
        private void indexManager_IndexingError(Exception e)
        {
            if (e is COMException)
            {
                MessageBox.Show("Exchange Server cannot be connected or permission denied. " +
                    "Check the Url, username and password then try again.",
                    "PfRep", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else
            {
                MessageBox.Show("An unknown error occurred while indexing the folders. " +
                    "For more information see the trace log (debug version only) " +
                    e.Message, "PfRep", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Updating the progress bar on progress change
        /// </summary>
        /// <param name="currentItemName"></param>
        /// <param name="currentItemUrl"></param>
        /// <param name="itemNumber"></param>
        private void IndexManager_ProgressChanges(
            string currentItemName,
            string currentItemUrl,
            int currentItemNumber,
            int itemCount)
        {
            // Set the maximum value for the progressbar
            if (IndexingProgress.Maximum < itemCount && itemCount > 0)
                IndexingProgress.Maximum = itemCount;

            // Set the progressbar
            IndexingProgress.Value = currentItemNumber;

            // Show text progress
            lblCurrentItem.Text = currentItemName;
            lblProgress.Text = string.Format("Folders {0} of {1}", currentItemNumber, itemCount);
            lblPercent.Text = string.Format("{0:0}%", (currentItemNumber / ((double)itemCount / (double)100)));
        }

        /// <summary>
        /// Called when the indexing is completed
        /// </summary>
        private void indexManager_IndexingCompleted()
        {
            // Close the window
            this.Close();
        }
        #endregion

        /// <summary>
        /// OK button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdOK_Click(object sender, EventArgs e)
        {
            // Starts indexing
            StartIndexing();
        }

        /// <summary>
        /// Cancel button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdCancel_Click(object sender, EventArgs e)
        {
            // Kill the thread if it's already running
            if (backgroundIndexingThread != null)
                backgroundIndexingThread.Abort();
            
            UserCancelled = true;
        }

        /// <summary>
        /// Textbox changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtContentStatisticsName_TextChanged(object sender, EventArgs e)
        {
            SetOkButton();
        }

        /// <summary>
        /// Textbox changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtPublicFolderTree_TextChanged(object sender, EventArgs e)
        {
            SetOkButton();
        }

        /// <summary>
        /// Saves the input controls' values
        /// </summary>
        private void SaveInputControlValues()
        {
            // Save the username and last URL
            Common.Config.SetConfigValue("LastUsername", txtUsername.Text);

            // Refresh the configuration
            Common.Config.RefreshConfig();
        }

        /// <summary>
        /// Fills up the controls in the form with the previously
        /// used values if there are any
        /// </summary>
        private void FillUpControlsWithPastValues()
        {
            // Fill up the input controls
            txtUsername.Text = Common.Config.GetConfigValue("LastUsername");
        }

        private void IndexContentStatistics_Load(object sender, EventArgs e)
        {
            this.Refresh();
            this.Update();
            
            // Sets up controls with unattended values
            txtUsername.Text = Username;
            txtPassword.Text = Password;

            // Sets a default value for the content statistics name
            txtContentStatisticsName.Text = "Content index created at " + DateTime.Now.ToString("f");

            // If requested, starts automatically            
            if (StartAutomatically)
            {
                StartIndexing();
            }
            else
            {
                // Otherwise, fills up the username with the previously user text if it's not
                //  a hands-free processing
                FillUpControlsWithPastValues();
            }
        }
    }
}